﻿using System;
using System.Collections.Generic;
using System.Text;

namespace RuyeeModbus
{
    public class ModbusRTUSlave
    {
        System.IO.Ports.SerialPort sp;


        public string COMName
        {
            get { return sp.PortName; }
        }

        public int Baudrate
        {
            get { return sp.BaudRate; }
        }

        public ModbusRTUSlave(string PortName, int BaudRate, int readTimeOut, int writeTimeOut)
        {
            sp = new System.IO.Ports.SerialPort(PortName, BaudRate);
            sp.ReadTimeout = readTimeOut;
            sp.WriteTimeout = writeTimeOut;
        }

        public bool OpenPort()
        {
            if (!sp.IsOpen)
            {
                sp.Open();
            }
            return sp.IsOpen;
        }
        /// <summary>
        /// 读取多个寄存器，串口通信采取同步模式
        /// </summary>
        /// <param name="startAddress">起始地址</param>
        /// <param name="count">读取个数</param>
        /// <param name="selfAddress">节点地址</param>
        /// <returns>获取同步串口通信的request字节流</returns>
        public byte[] ReadHoldingRegisters(UInt16 startAddress, UInt16 count, byte selfAddress)
        {
            byte startAddressH = (byte)(startAddress >> 8);
            byte startAddressL = (byte)(startAddress << 8 >> 8);
            byte countH = (byte)(count >> 8);
            byte countL = (byte)(count << 8 >> 8);
            byte[] ba = new byte[] { selfAddress, 03, startAddressH, startAddressL, countH, countL, 0xff, 0xff };
            OpenPort();
            ushort x = RuyeeModbus.CRC.CRC16(ba, 0, ba.Length - 2);
            ba[ba.Length - 1] = (byte)(x >> 8);
            ba[ba.Length - 2] = (byte)(x << 8 >> 8);
            sp.Write(ba, 0, ba.Length);
            byte[] requestBuffer = new byte[count * 2 + 5];
            int i = 0;
            try
            {
                while (i < count * 2 + 5)
                {
                    byte temp = sp.IsOpen == true ? (byte)sp.ReadByte() : (byte)0;
                    requestBuffer[i] = temp;
                    i++;
                }
            }
            catch
            { }
            return requestBuffer;
        }


        public void ClosePort()
        {
            try
            {
                sp.Close();
            }
            catch
            { }
        }
    }
}
